#include <iostream>
#include <stdlib.h>

struct node
{
	int val;
	struct node *next;
};

typedef struct node *secuencia;

struct jagged
{
	int *arreglo;
	int size;
};

typedef struct jagged **jaggedArray;

typedef struct
{
	int size;
	void *number;
} bigint;

struct bstNode
{
	struct bstNode *left;
	int val;
	struct bstNode *right;
};

typedef struct bstNode *BST;

extern "C"
{
	int exceptionGenerator();

	int sumaYDivideRegister(int a, int b, int c, int d, int div);

	int sumarTodo(char c1, char c2, char c3, char c4, int a, int b)
	{
		return c1 + c2 + c3 + c4 + b + a;
	}

	int sumarDos(int a, int b)
	{
		int c = exceptionGenerator();
		return a + b;
	}

	float sumarCharIntFloat(char c, int i, float f)
	{
		return f + (float) i + (float) c;
		
		//return 12.5;
	}

	int funcionConstante()
	{
		return 23;
	}

	void metodoConstante(const char *msg)
	{
		printf("%s", msg);
	}

	secuencia reeplaceElemAtPosition(secuencia secu, int index, int val)
	{
		struct node *nodo = secu;
		printf("secu es %X \n", secu);
		while (nodo != NULL)
		{
			printf("nodo->val = %d, nodo->next = %p\n", nodo->val, nodo->next);
			if (index == 0){				
				nodo->val=val;
				return secu;
			}
			
			index--;
			nodo = nodo->next;
		}

		return secu;
	}


	int elemAtPosition(secuencia secu, int index)
	{
		struct node *nodo = secu;

		//FILE *log = NULL;
		
		////fopen_s(&log, "log.txt", "a");
		//log = fopen("log.txt", "a");

		//fprintf(log, "secu = %p, index = %d\n", secu, index);

		while (nodo != NULL)
		{
			//fprintf(log, "nodo->val = %d, nodo->next = %p\n", nodo->val, nodo->next);

			if (index == 0)
				return nodo->val;
			
			index--;
			nodo = nodo->next;
		}

		//fclose(log);
		return -1;
	}

	int* sumarUno(int* arr, int len)
	{
		for(int i=0;i<len;i++)
			arr[i]+=1;

		return arr;
	}

	int** sumarMatrices(int** a, int** b,int alto, int ancho)
	{
		for(int i=0;i<alto;i++)
			for(int j=0;j<ancho;j++)
				a[i][j]+=b[i][j];

		return a;
	}

	float* sumarUnoFloat(float* arr, int len)
	{
		for(int i=0;i<len;i++)
			arr[i]+=3.14f;

		return arr;
	}

	
	int length(secuencia secu)
	{
		struct node *nodo = secu;
		int result = 0;

		while (nodo != NULL)
		{
			result++;
			nodo = nodo->next;
		}

		printf("Hola mundo!");

		return result;
	}

	int sumarArreglo(int *arreglo, int size)
	{
		printf("Empiezo a sumar arreglo %p de tamanio %d\n",arreglo,size);
		int result = 0;

		for (int i = 0; i < size; i++){
			result += arreglo[i];
			printf("Sumando arreglo en %d \n",i);
		}

		return result;
	}

	int sumarMatriz(int **matriz, int size)
	{
		int result = 0;

		for (int i = 0; i < size; i++)
			for (int j = 0; j < size; j++)
				result += matriz[i][j];

		return result;
	}

	int sumarJaggedArray(jaggedArray arreglo, int size)
	{
		int result = 0;

		for (int i = 0; i < size; i++)
			for (int j = 0; j < arreglo[i]->size; j++)
				result += arreglo[i]->arreglo[j];

		return result;
	}

	int stringLength(const char *text)
	{
		int i = 0;

		while (text[i] != NULL)
			i++;

		return i;
	}

	long long sumarLongArray(long long *arreglo, int size)
	{
		long long result = 0;

		for (int i = 0; i < size; i++)
			result += arreglo[i];

		return result;
	}

	double sumarDoubles(double *arreglo, int size)
	{
		double result = 0;
		
		for (int i = 0; i < size; i++)
			result += arreglo[i];

		return result;
	}

	float sumarFloats(float *arreglo, int size)
	{
		float result = 0;
		
		for (int i = 0; i < size; i++)
			result += arreglo[i];

		return result;
	}

	int compareBigints(bigint *a, bigint *b)
	{
		if (a->size != b->size)
			return 0;

		char *num1 = (char *) a->number;
		char *num2 = (char *) b->number;

		for (int i = 0; i < a->size; i++)
			if (num1[i] != num2[i])
				return 2;
		
		return 1;
	}

	bigint *sumarBigints(bigint *a, bigint *b)
	{
		if (a->size != b->size)
			return 0;

		bigint *result = new bigint;

		result->size = a->size + 1;
		char *num3 = new char[result->size];
		result->number = (void *) num3;

		char *num1 = (char *) a->number;
		char *num2 = (char *) b->number;
		int carry = 0;

		for (int i = 0; i < a->size; i++)
		{
			num3[i] = num1[i] + num2[i] + carry;
			carry = num1[i] + num2[i] + carry > 255 ? 1 : 0;
		}
		
		num3[a->size] = carry;
		return result;
	}

	char *reemplazar(char *str)
	{
		str[0] = 'W';
		printf("address: %p, char: '%c', char: '%d', #W: %d", str, str[0], str[0], 'W');
		return str;
	}

	char *reemplazarLetra(char *str, char a, char b)
	{
		for (int i = 0; str[i] != NULL; i++)
			if (str[i] == a)
				str[i] = b;

		return str;
	}

	char caracterEn(char *str, int a)
	{
		return str[a];
	}

	int addChoto(int a, int b)
	{
		return a+b;
	}

	int and(int p, int q)
	{
		return p && q;
	}

	char firstChar(const char *str)
	{
		return str[0];
	}

	BST addBSTNode(BST tree, int val)
	{
		if (tree == NULL)
		{
			BST node = new struct bstNode();
			node->val = val;
			return node;
		}

		if (tree->val >= val)
			tree->left = addBSTNode(tree->left, val);
		else
			tree->right = addBSTNode(tree->right, val);

		return tree;
	}

	int getBSTCount(BST tree)
	{
		if (tree == NULL)
			return 0;
		else
			return getBSTCount(tree->left) + getBSTCount(tree->right) + 1;
	}

	char *getBSTInOrder(BST tree)
	{
		if (tree == NULL)
			return "";
		else
		{
			char *res1 = getBSTInOrder(tree->left);
			char *res2 = getBSTInOrder(tree->right);

			int len = strlen(res1) + strlen(res2) + 10;
			char *res = new char[len];

			sprintf(res, "%s%d,%s", res1, tree->val, res2);
			return res;
		}
	}
}
